/* Especificacao lexica para a linguagem Python */
import java_cup.runtime.*;

%%
%class AnalisadorLexico
%unicode
%cup
%line
%column
 
/* Codigo Java */

%{

  private String fileName;
  
  public void setFileName(String fileName) {
  	this.fileName = fileName;
  }
  
  public String getFileName() {
  	if (this.fileName == null) {
  	  throw new RuntimeException("fileName nao definido");
  	}
  	return this.fileName;
  }

  StringBuffer string = new StringBuffer();

  private Symbol symbol(int type) {
    return new Symbol(type, yyline, yycolumn);
  }
  private Symbol symbol(int type, String name) {
  	int line = yyline + 1;
  	ParseNode node = new ParseNode(type, name, this.fileName, yytext(), line);
    return new Symbol(type, yyline, yycolumn, node);
  }
     
%}



/* Expressoes Regulares */

LineTerminator = "\r" | "\n" | "\r\n"

LowerCase = [a-z]
UpperCase = [A-Z]
Letter = {LowerCase} | {UpperCase}
Digit = [0-9]
OctDigit = [0-7]
HexDigit = {Digit} | [a-f] | [A-F]
NonZeroDigit = [1-9]
Whitespace = [ \r\n\t\f]

Comment = "#".* {LineTerminator}

StringPrefix = "r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"
ShortString = "'" {ShortStringItem}* "'" | "\"" {ShortStringItem}* "\""
LongString = "'''" {LongStringItem}* "'''" | "\"\"\"" {LongStringItem}* "\"\"\""
ShortStringItem = {ShortStringChar} | {EscapeSeq}
LongStringItem = {LongStringChar} | {EscapeSeq}
ShortStringChar = [^\r\n\\]
LongStringChar = [^\\]
EscapeSeq = "\\".*

Indent = ("    ")* 

PointFloat = {IntPart}? ({Fraction} | {IntPart}) "."
ExponentFloat = ({IntPart} | {PointFloat}) {Exponent}
IntPart = {Digit}+
Fraction = "." {Digit}+
Exponent = (("e" | "E") ("+" | "-"))? {Digit}+


DecInteger= "0" | {NonZeroDigit} {Digit}*
OctInteger = "0" {OctDigit}+
HexInteger = "0" ("x" | "X") {HexDigit}+

StringLiteral = {StringPrefix}?({ShortString} | {LongString})
LongIntegerLiteral = {IntegerLiteral}("l" | "L")
FloatNumberLiteral = {PointFloat} | {ExponentFloat}
IntegerLiteral = {DecInteger} | {OctInteger} | {HexInteger}
ImgNumberLiteral = ({FloatNumberLiteral} | {IntPart}) ("j" | "J")
Boolean = "True" | "False"

Literal = {StringLiteral} | {IntegerLiteral} | {LongIntegerLiteral} | {FloatNumberLiteral} | {ImgNumberLiteral} | {Boolean}


Identifier = ({Letter} | "_") ({Letter} | {Digit} | "_")*

%%

/* Comentarios */
  {Comment} { }

 /* Palavras Chave*/
 "if"              { return symbol(AnalisadorSintaticoSym.IF, yytext()); }
 "as"              { return symbol(AnalisadorSintaticoSym.AS, yytext());}
 "elif"            { return symbol(AnalisadorSintaticoSym.ELIF, yytext()); }
 "else"            { return symbol(AnalisadorSintaticoSym.ELSE, yytext()); } 
 "while"           { return symbol(AnalisadorSintaticoSym.WHILE, yytext()); }
 "for"             { return symbol(AnalisadorSintaticoSym.FOR, yytext()); }
 "with"            { return symbol(AnalisadorSintaticoSym.WITH, yytext()); }
 "def"             { return symbol(AnalisadorSintaticoSym.DEF, yytext()); }
 "and"             { return symbol(AnalisadorSintaticoSym.AND, yytext()); }
 "or"              { return symbol(AnalisadorSintaticoSym.OR, yytext());}
 "return"          { return symbol(AnalisadorSintaticoSym.RETURN, yytext());}
 "not"             { return symbol(AnalisadorSintaticoSym.NOT, yytext());}
 "continue"        { return symbol(AnalisadorSintaticoSym.CONTINUE, yytext());}
 "break"           { return symbol(AnalisadorSintaticoSym.BREAK, yytext());}
 "in"              { return symbol(AnalisadorSintaticoSym.IN, yytext());}
 "is"              { return symbol(AnalisadorSintaticoSym.NOT, yytext());}
 "print"           { return symbol(AnalisadorSintaticoSym.PRINT, yytext());}

/* Operadores*/
 "="        		{ return symbol(AnalisadorSintaticoSym.ASSIGN, yytext());}

/* Aritmeticos*/
 "-"        		{ return symbol(AnalisadorSintaticoSym.MINUS, yytext());}
 "+"           	{ return symbol(AnalisadorSintaticoSym.PLUS, yytext());}
 "*"           	{ return symbol(AnalisadorSintaticoSym.MULTIPLY, yytext());}
 "/"           	{ return symbol(AnalisadorSintaticoSym.DIVIDE, yytext());}
 "//"           	{ return symbol(AnalisadorSintaticoSym.DIVIDE_INTEGER, yytext());}
 "**"           	{ return symbol(AnalisadorSintaticoSym.EXPONENTIAL, yytext());}
 "%"           	{ return symbol(AnalisadorSintaticoSym.MOD, yytext());}
 "<<"              { return symbol(AnalisadorSintaticoSym.SHIFT_LEFT, yytext());}
 ">>"              { return symbol(AnalisadorSintaticoSym.SHIFT_RIGHT, yytext());}
 "-="           	{ return symbol(AnalisadorSintaticoSym.MINUS_EQUAL, yytext());}
 "+="           	{ return symbol(AnalisadorSintaticoSym.PLUS_EQUAL, yytext());}
 "*="           	{ return symbol(AnalisadorSintaticoSym.MULTIPLY_EQUAL, yytext());}
 "/="           	{ return symbol(AnalisadorSintaticoSym.DIVIDE_EQUAL, yytext());}
 "//="           	{ return symbol(AnalisadorSintaticoSym.DIVIDE_INTEGER_EQUAL, yytext());}


/* Bitwise */
 "&"              { return symbol(AnalisadorSintaticoSym.BITWISE_AND, yytext());}
 "|"              { return symbol(AnalisadorSintaticoSym.BITWISE_OR, yytext());}
 "^"              { return symbol(AnalisadorSintaticoSym.BITWISE_XOR, yytext());}
 "~"              { return symbol(AnalisadorSintaticoSym.BITWISE_NOT, yytext());}
 "&="             { return symbol(AnalisadorSintaticoSym.BITWISE_AND_EQUAL, yytext());}
 "|="             { return symbol(AnalisadorSintaticoSym.BITWISE_OR_EQUAL, yytext());}
 "^="              { return symbol(AnalisadorSintaticoSym.BITWISE_XOR_EQUAL, yytext());}
 "%="              { return symbol(AnalisadorSintaticoSym.MOD_EQUAL, yytext());}
 "**="             { return symbol(AnalisadorSintaticoSym.EXPONENTIAL_EQUAL, yytext());}
 "<<="             { return symbol(AnalisadorSintaticoSym.SHIFT_LEFT_EQUAL, yytext());}
 ">>="             { return symbol(AnalisadorSintaticoSym.SHIFT_RIGHT_EQUAL, yytext());}

/* Comparacao */
 "=="           	{ return symbol(AnalisadorSintaticoSym.EQUAL, yytext());}
 "!=" | "<>"       	{ return symbol(AnalisadorSintaticoSym.NOT_EQUAL, yytext());}
 ">"           	{ return symbol(AnalisadorSintaticoSym.GREATER_THAN, yytext());}
 "<"           	{ return symbol(AnalisadorSintaticoSym.LESS_THAN, yytext());}
 ">="           	{ return symbol(AnalisadorSintaticoSym.GREATER_EQUAL_THAN, yytext());}
 "<="           	{ return symbol(AnalisadorSintaticoSym.LESS_EQUAL_THAN, yytext());}



/* Pontuacao */

 "("      		{ return symbol(AnalisadorSintaticoSym.LEFT_PARENTHESIS, yytext());}
 ")"           	{ return symbol(AnalisadorSintaticoSym.RIGHT_PARENTHESIS, yytext());}
 "["           	{ return symbol(AnalisadorSintaticoSym.OPEN_BRACKETS, yytext());}
 "]"           	{ return symbol(AnalisadorSintaticoSym.CLOSE_BRACKETS, yytext());}
 ":"           	{ return symbol(AnalisadorSintaticoSym.COLON, yytext());}
 ";"           	{ return symbol(AnalisadorSintaticoSym.SEMI_COLON, yytext());}
 "."           	{ return symbol(AnalisadorSintaticoSym.DOT, yytext());}
 ","           	{ return symbol(AnalisadorSintaticoSym.COMMA, yytext());}

/* Literais */
 {Literal}      { return symbol(AnalisadorSintaticoSym.LITERAL, yytext());}
 

/* Outros */

{LineTerminator}  { return symbol(AnalisadorSintaticoSym.NEWLINE, yytext()); }
{Identifier}      { return symbol(AnalisadorSintaticoSym.IDENTIFIER, yytext());}
{Whitespace}      { }
{Indent}          { return symbol(AnalisadorSintaticoSym.INDENT, yytext());}
<<EOF>>           { return symbol(AnalisadorSintaticoSym.EOF, yytext());}
